home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / oleo-1_4.lha / oleo-1.4 / byte-compile.c < prev    next >
C/C++ Source or Header  |  1993-05-23  |  23KB  |  875 lines

  1. /*    Copyright (C) 1990, 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. This file is part of Oleo, the GNU Spreadsheet.
  4.  
  5. Oleo is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9.  
  10. Oleo is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with Oleo; see the file COPYING.  If not, write to
  17. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "funcdef.h"
  20. #include <stdio.h>
  21.  
  22. #define obstack_chunk_alloc ck_malloc
  23. #define obstack_chunk_free free
  24. #include "obstack.h"
  25.  
  26. #include "sysdef.h"
  27. #include "global.h"
  28. #include "node.h"
  29. #include "eval.h"
  30. #include "hash.h"
  31. #include "ref.h"
  32.  
  33.  
  34. #ifdef __STDC__
  35. extern int yyparse (void);
  36. #else
  37. extern int yyparse ();
  38. #endif
  39.  
  40. extern struct function date_funs[];
  41. extern struct function busi_funs[];
  42. extern struct function string_funs[];
  43. extern struct function cells_funs[];
  44. extern char *instr;
  45. extern int parse_error;
  46. extern struct node *parse_return;
  47. extern void sort ();
  48.  
  49.  
  50. #ifdef __STDC__
  51. static void add_backpatch (unsigned, unsigned);
  52. #else
  53. static void add_backpatch ();
  54. #endif
  55.  
  56. struct backpatch
  57.   {
  58.     unsigned from, to;
  59.   };
  60.  
  61. static struct backpatch *patches;
  62. static int patches_allocated;
  63. static int patches_used;
  64. static void *fn_stack;
  65. static void *str_stack;
  66. struct obstack tmp_mem;
  67. void *tmp_mem_start;
  68.  
  69.  
  70. #define V (void(*)())
  71.  
  72. /* These have to go in some file or other, so it is stuck in here (for now).
  73.  */
  74. struct function the_funs[] =
  75. {
  76.   {0, X_A0, "", 0, "<END>"},
  77.   {0, X_A0, "", 0, "<DUMMY1>"},
  78.  
  79.   {C_IF | R | INF (1), X_A1 | X_J, "D", 0, "?"},
  80.   {C_IF | R | INF (1), X_A1 | X_JL, "D", 0, "?"},
  81.   {C_IF, X_A1 | X_J, "D", 0, "if"},
  82.   {C_IF, X_A1 | X_JL, "D", 0, "if"},
  83.   {C_ANDOR, X_A1 | X_J, "D", 0, "and"},
  84. /* { C_ANDOR|L|INF(3), X_A1, "DD", 0,        "&" }, */
  85.   {C_ANDOR, X_A1 | X_JL, "D", 0, "and"},
  86. /* { C_ANDOR|L|INF(3), X_A1, "DD", 0,        "&" }, */
  87.   {C_ANDOR, X_A1 | X_J, "D", 0, "or"},
  88. /* { C_ANDOR|L|INF(2), X_A1, "DD", 0,        "|" }, */
  89.   {C_ANDOR, X_A1 | X_JL, "D", 0, "or"},
  90. /* { C_ANDOR|L|INF(2), X_A1, "DD", 0,        "|" }, */
  91.   {C_STR, X_A0 | X_J, "", 0, "\"%s\""},
  92.   {C_STR, X_A0 | X_JL, "", 0, "\"%s\""},
  93.  
  94.   {C_CELL, X_A0, "", 0, "$%s$%u"},
  95.   {C_CELL, X_A0, "", 0, "$%s%u"},
  96.   {C_CELL, X_A0, "", 0, "%s$%u"},
  97.   {C_CELL, X_A0, "", 0, "%s%u"},
  98.   {C_RANGE, X_A0, "", 0, "$%s$%u:$%s$%u"},
  99.   {C_RANGE, X_A0, "", 0, "$%s%u:$%s$%u"},
  100.   {C_RANGE, X_A0, "", 0, "$%s$%u:$%s%u"},
  101.   {C_RANGE, X_A0, "", 0, "$%s%u:$%s%u"},
  102.   {C_RANGE, X_A0, "", 0, "%s$%u:$%s$%u"},
  103.   {C_RANGE, X_A0, "", 0, "%s%u:$%s$%u"},
  104.   {C_RANGE, X_A0, "", 0, "%s$%u:$%s%u"},
  105.   {C_RANGE, X_A0, "", 0, "%s%u:$%s%u"},
  106.   {C_RANGE, X_A0, "", 0, "$%s$%u:%s$%u"},
  107.   {C_RANGE, X_A0, "", 0, "$%s%u:%s$%u"},
  108.   {C_RANGE, X_A0, "", 0, "$%s$%u:%s%u"},
  109.   {C_RANGE, X_A0, "", 0, "$%s%u:%s%u"},
  110.   {C_RANGE, X_A0, "", 0, "%s$%u:%s$%u"},
  111.   {C_RANGE, X_A0, "", 0, "%s%u:%s$%u"},
  112.   {C_RANGE, X_A0, "", 0, "%s$%u:%s%u"},
  113.   {C_RANGE, X_A0, "", 0, "%s%u:%s%u"},
  114.  
  115.   {C_CONST, X_A0, "", 0, tname},
  116.   {C_CONST, X_A0, "", 0, fname},
  117.  
  118.   {C_CONST, X_A0, "", 0, iname},
  119.   {C_CONST, X_A0, "", 0, mname},
  120.   {C_CONST, X_A0, "", 0, nname},
  121.   {C_ERR, X_A0 | X_J, "", 0, "%s"},
  122.   {C_FLT, X_A0, "", 0, "%.15g"},
  123.   {C_INT, X_A0, "", 0, "%ld"},
  124.  
  125.   {C_VAR, X_A0, "", 0, "%s"},
  126.  
  127.   {C_UNA, X_A1, "F", 0, "-"},
  128.   {C_UNA, X_A1, "B", 0, "!"},
  129.  
  130.   {C_INF | L | INF (6), X_A2, "NN", 0, "-"},
  131.   {C_INF | L | INF (7), X_A2, "NN", 0, "/"},
  132.   {C_INF | L | INF (7), X_A2, "NN", 0, "%"},
  133.   {C_INF | L | INF (7), X_A2, "NN", 0, "*"},
  134.   {C_INF | L | INF (6), X_A2, "NN", 0, "+"},
  135.   {C_INF | L | INF (2), X_A2, "SS", 0, "&"},
  136.   {C_INF | N | INF (4), X_A2, "AA", 0, "="},
  137.   {C_INF | N | INF (5), X_A2, "AA", 0, ">="},
  138.   {C_INF | N | INF (5), X_A2, "AA", 0, ">"},
  139.   {C_INF | N | INF (5), X_A2, "AA", 0, "<"},
  140.   {C_INF | N | INF (5), X_A2, "AA", 0, "<="},
  141.   {C_INF | N | INF (4), X_A2, "AA", 0, "!="},
  142.   {C_INF | R | INF (8), X_A2, "FF", V pow, "^"},
  143.  
  144.   {C_FN0, X_A0, "", 0, "pi"},
  145.   {C_FN0X, X_A0, "", 0, "row"},
  146.   {C_FN0X, X_A0, "", 0, "col"},
  147.   {C_FN0 | C_T, X_A0, "", 0, "now"},
  148.  
  149.   {C_FN1, X_A1, "F", V fabs, "abs"},
  150.   {C_FN1, X_A1, "F", V acos, "acos"},
  151.   {C_FN1, X_A1, "F", V asin, "asin"},
  152.   {C_FN1, X_A1, "F", V atan, "atan"},
  153.   {C_FN1, X_A1, "F", V ceil, "ceil"},
  154.   {C_FN1, X_A1, "F", V to_int, "int"},
  155.   {C_FN1, X_A1, "F", V floor, "floor"},
  156.   {C_FN1, X_A1, "F", V cos, "cos"},
  157.   {C_FN1, X_A1, "F", V dtr, "dtr"},
  158.   {C_FN1, X_A1, "F", V exp, "exp"},
  159.   {C_FN1, X_A1, "F", V log, "log"},
  160.   {C_FN1, X_A1, "F", V log10, "log10"},
  161.   {C_FN1, X_A1, "F", V rtd, "rtd"},
  162.   {C_FN1, X_A1, "F", V sin, "sin"},
  163.   {C_FN1, X_A1, "F", V sqrt, "sqrt"},
  164.   {C_FN1, X_A1, "F", V tan, "tan"},
  165.   {C_FN1, X_A1, "I", 0, "ctime"},
  166.   {C_FN1, X_A1, "A", 0, "negate"},
  167.   {C_FN1, X_A1, "A", 0, "not"},
  168.   {C_FN1, X_A1, "A", 0, "iserr"},
  169.   {C_FN1, X_A1, "A", 0, "isnum"},
  170.  
  171.   {C_FN1 | C_T, X_A1, "I", 0, "rnd"},
  172.   {C_FN1, X_A1, "R", 0, "rows"},
  173.   {C_FN1, X_A1, "R", 0, "cols"},
  174.   {C_FN2, X_A2, "FF", V atan2, "atan2"},
  175. #ifdef HAVE_HYPOT
  176.   {C_FN2, X_A2, "FF", V hypot, "hypot"},
  177. #else
  178.   {C_FN2, X_A2, "FF", 0, "*&%$%*"},
  179. #endif
  180.   {C_FN2, X_A2, "FI", 0, "fixed"},
  181.   {C_FN2, X_A2, "AA", 0, "iferr"},
  182.   {C_FN2, X_A2, "RI", 0, "index"},
  183.   {C_FN3, X_A3, "RII", 0, "index"},
  184.   {C_FNN, X_AN, "IAAA", 0, "oneof"},
  185.  
  186.   {C_FNN, X_AN, "SIIA", 0, "file"},
  187.   {C_FNN, X_AN, "EEEE", 0, "sum"},
  188.   {C_FNN, X_AN, "EEEE", 0, "prod"},
  189.   {C_FNN, X_AN, "EEEE", 0, "avg"},
  190.   {C_FNN, X_AN, "EEEE", 0, "std"},
  191.   {C_FNN, X_AN, "EEEE", 0, "max"},
  192.   {C_FNN, X_AN, "EEEE", 0, "min"},
  193.   {C_FNN, X_AN, "EEEE", 0, "count"},
  194.   {C_FNN, X_AN, "EEEE", 0, "var"},
  195.  
  196. };
  197.  
  198. #ifdef USE_DLD
  199. int n_usr_funs;
  200. struct function **usr_funs;
  201. int *usr_n_funs;
  202. #else
  203. int n_usr_funs = 4;
  204. static struct function *__usr_funs[] =
  205. {
  206.   date_funs,
  207.   busi_funs,
  208.   string_funs,
  209.   cells_funs,
  210. };
  211. static int __usr_n_funs[] =    /* Dear hack, this is stupid. never do this. */
  212. {                /* Maintaining this is a big waste of time. */
  213.   32, 18, 11, 10        /* Grrr. */
  214. };                /* I mean it. */
  215.  
  216. struct function **usr_funs = __usr_funs;
  217. int *usr_n_funs = __usr_n_funs;
  218. #endif
  219.  
  220. /* ... A whole huge empty space, then ... */
  221. struct function skip_funs[] =
  222. {
  223.   {C_SKIP, X_A0 | X_J, "", 0, "<Skip %u>"},
  224.   {C_SKIP, X_A0 | X_JL, "", 0, "<SkipL %u>"},
  225. };
  226.  
  227. /* The memory allocated here is used for several things, but byte_compile
  228.    is a small file, so it might as well be here */
  229. void
  230. init_mem ()
  231. {
  232.   int n;
  233.  
  234.   parse_hash = hash_new ();
  235.   hash_insert (parse_hash, the_funs[F_IF].fn_str, &the_funs[F_IF]);
  236.   hash_insert (parse_hash, the_funs[AND].fn_str, &the_funs[AND]);
  237.   hash_insert (parse_hash, the_funs[OR].fn_str, &the_funs[OR]);
  238.   for (n = F_PI; n < USR1; n++)
  239.     hash_insert (parse_hash, the_funs[n].fn_str, &the_funs[n]);
  240. #ifndef USE_DLD
  241.   for (n = 0; n < n_usr_funs; n++)
  242.     {
  243.       int nn;
  244.  
  245.       for (nn = 0; usr_funs[n][nn].fn_str; nn++)
  246.     hash_insert (parse_hash, usr_funs[n][nn].fn_str, &usr_funs[n][nn]);
  247. #ifdef TEST
  248.       if (usr_n_funs[n] != nn)
  249.     {
  250.       fprintf (stderr, "Usr_n_funs[%d]%d!=%d", n, usr_n_funs[n], nn);
  251.       usr_n_funs[n] = nn;
  252.  
  253.     }
  254. #endif
  255.     }
  256. #endif
  257.   fn_stack = init_stack ();
  258.   str_stack = init_stack ();
  259.   obstack_begin (&tmp_mem, 400);
  260.   tmp_mem_start = obstack_alloc (&tmp_mem, 0);
  261. }
  262.  
  263. #ifdef USE_DLD
  264. void
  265. add_usr_funs (new_funs)
  266.      struct function *new_funs;
  267. {
  268.   int n;
  269.  
  270.   n_usr_funs++;
  271.   usr_funs = usr_funs ? ck_realloc (usr_funs, n_usr_funs * sizeof (struct function *)) : ck_malloc (sizeof (struct function *));
  272.   usr_n_funs = usr_n_funs ? ck_realloc (usr_n_funs, n_usr_funs * sizeof (int)) : ck_malloc (sizeof (int));
  273.  
  274.   usr_funs[n_usr_funs - 1] = new_funs;
  275.   for (n = 0; new_funs[n].fn_str; n++)
  276.     hash_insert (parse_hash, new_funs[n].fn_str, &new_funs[n]);
  277.   usr_n_funs[n_usr_funs - 1] = n;
  278. }
  279.  
  280. #endif
  281.  
  282. /* Stash away a backpatch for future editing. */
  283. static void
  284. add_backpatch (from, to)
  285.      unsigned from;
  286.      unsigned to;
  287. {
  288.   if (!patches)
  289.     {
  290.       patches_allocated = 5;
  291.       patches = (struct backpatch *) ck_malloc (patches_allocated * sizeof (struct backpatch));
  292.       patches_used = 0;
  293.     }
  294.   if (patches_allocated == patches_used)
  295.     {
  296.       patches_allocated *= 2;
  297.       patches = (struct backpatch *) ck_realloc (patches, patches_allocated * sizeof (struct backpatch));
  298.     }
  299.   patches[patches_used].from = from;
  300.   patches[patches_used].to = to;
  301.   patches_used++;
  302. }
  303.  
  304. static int
  305. cmp_patch (n1, n2)
  306.      int n1;
  307.      int n2;
  308. {
  309.   int ret;
  310.  
  311.   ret = (patches[n1].from == patches[n2].from) ? patches[n1].to - patches[n2].to : patches[n1].from - patches[n2].from;
  312.   return ret;
  313. }
  314.  
  315. static void
  316. swp_patch (n1, n2)
  317.      int n1;
  318.      int n2;
  319. {
  320.   struct backpatch tmp;
  321.  
  322.   tmp = patches[n1];
  323.   patches[n1] = patches[n2];
  324.   patches[n2] = tmp;
  325. }
  326.  
  327. static void
  328. rot_patch (n1, n2)
  329.      int n1;
  330.      int n2;
  331. {
  332.   struct backpatch tmp;
  333.   tmp = patches[n2];
  334.   while (n2 > n1)
  335.     {
  336.       patches[n2] = patches[n2 - 1];
  337.       --n2;
  338.     }
  339.   patches[n2] = tmp;
  340. }
  341.  
  342.  
  343. /* This takes an ascii string and returns a pointer to the byte-compiled
  344.    result.  It calls yyparse() to do the actual parsing.  This is complicated
  345.    only because yyparse returns a parse tree which needs to be turned into
  346.    postfix compiled bytes.  This is further complicated by the presence of
  347.    forward branches in the byte-compiled code.  That's what the backpatch
  348.    stuff is for.
  349.  
  350.    It'd be nice if oneof() could compile into
  351.    arg1
  352.    ONEOF n_possibilities
  353.    JUMP poss1
  354.    JUMP poss2
  355.    JUMP poss3
  356.    ...
  357.    JUMP error
  358.    {poss 1}
  359.    JUMP end
  360.    {poss 2}
  361.    JUMP end
  362.    ...
  363.    end: {rest of expression}
  364.    instead of the simplistic (and slow-to-execute) version currently used
  365.  
  366.    It'd also be nice if byte-compiled expressions could have *BIG*
  367.    subexpressions, instead of silently failing as they do now.  Error checking
  368.    and a way to encode longer branches would be a *good* idea.
  369.  */
  370. unsigned char *
  371. parse_and_compile (string)
  372.      char *string;
  373. {
  374.   struct node *new_node;
  375.   struct node *node;
  376.   const struct function *f;
  377.   unsigned char *ret;
  378.   int n;
  379.   unsigned buf_siz;
  380.   int need_relax;
  381.   int byte;
  382.  
  383.   instr = string;
  384.   parse_error = 0;
  385.   patches_used = 0;
  386.   if (yyparse () || parse_error)
  387.     {
  388.       ret = ck_malloc (strlen (string) + 5);
  389.       ret[0] = CONST_ERR;
  390.       ret[1] = 2;
  391.       ret[2] = parse_error;
  392.       ret[3] = ENDCOMP;
  393.       strcpy ((char *) &ret[4], string);
  394.       (void) obstack_free (&tmp_mem, tmp_mem_start);
  395.       return ret;
  396.     }
  397.  
  398.   node = parse_return;
  399.   if (!node)
  400.     return 0;
  401.  
  402. loop:
  403.   if (node->comp_value < USR1)
  404.     {
  405.       f = &the_funs[node->comp_value];
  406.     }
  407.   else if (node->comp_value < SKIP)
  408.     {
  409.       n = node->sub_value;
  410.       f = &usr_funs[node->comp_value - USR1][n];
  411.     }
  412.   else
  413.     {
  414.       f = &skip_funs[node->comp_value - SKIP];
  415.     }
  416.   byte = node->comp_value;
  417.  
  418. #ifdef TEST
  419.   if (!f)
  420.     panic ("f is zero in byte_compile!");
  421. #endif
  422.   switch (GET_COMP (f->fn_comptype))
  423.     {
  424.     case C_IF:
  425.       /* if compiles to
  426.            test-code IF amt-to-skip-on-false true-code SKIP
  427.                amt-to-skip-on-true false-code */
  428.       if (node->n_x.v_subs[0])
  429.     {
  430.       if (node->n_x.v_subs[0]->n_x.v_subs[0])
  431.         {
  432.           /* Put out the test-code */
  433.           push_stack (fn_stack, node);
  434.           new_node = node->n_x.v_subs[0]->n_x.v_subs[0];
  435.           node->n_x.v_subs[0]->n_x.v_subs[0] = 0;
  436.           node = new_node;
  437.           goto loop;
  438.         }
  439.       /* Put out IF, null-byte to backpatch */
  440.       (void) obstack_1grow (&tmp_mem, byte);
  441.       node->add_byte = obstack_object_size (&tmp_mem);
  442.       (void) obstack_1grow (&tmp_mem, 0);
  443.  
  444.       /* put out true-code */
  445.       push_stack (fn_stack, node);
  446.       new_node = node->n_x.v_subs[0]->n_x.v_subs[1];
  447.       node->n_x.v_subs[0] = 0;
  448.       node = new_node;
  449.       goto loop;
  450.     }
  451.       if (node->n_x.v_subs[1])
  452.     {
  453.  
  454.       (void) obstack_1grow (&tmp_mem, (char)SKIP);
  455.       (void) obstack_1grow (&tmp_mem, 0);
  456.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  457.       node->add_byte = obstack_object_size (&tmp_mem) - 1;
  458.  
  459.       push_stack (fn_stack, node);
  460.       new_node = node->n_x.v_subs[1];
  461.       node->n_x.v_subs[1] = 0;
  462.       node = new_node;
  463.       goto loop;
  464.     }
  465.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  466.       break;
  467.  
  468.     case C_ANDOR:
  469.       if (node->n_x.v_subs[0])
  470.     {
  471.       push_stack (fn_stack, node);
  472.       new_node = node->n_x.v_subs[0];
  473.       node->n_x.v_subs[0] = 0;
  474.       node = new_node;
  475.       goto loop;
  476.     }
  477.       if (node->n_x.v_subs[1])
  478.     {
  479.       (void) obstack_1grow (&tmp_mem, byte);
  480.       node->add_byte = obstack_object_size (&tmp_mem);
  481.       (void) obstack_1grow (&tmp_mem, 0);    /* for backpatching */
  482.       push_stack (fn_stack, node);
  483.       new_node = node->n_x.v_subs[1];
  484.       node->n_x.v_subs[1] = 0;
  485.       node = new_node;
  486.       goto loop;
  487.     }
  488.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  489.       break;
  490.  
  491.     case C_ERR:
  492.       (void) obstack_1grow (&tmp_mem, byte);
  493.       node->add_byte = obstack_object_size (&tmp_mem);
  494.       (void) obstack_1grow (&tmp_mem, 0);
  495.       (void) obstack_1grow (&tmp_mem, node->n_x.v_int);
  496.       node->n_x.v_string = ename[node->n_x.v_int];
  497.       push_stack (str_stack, node);
  498.       break;
  499.  
  500.     case C_FLT:
  501.       (void) obstack_1grow (&tmp_mem, byte);
  502.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_float), sizeof (double));
  503.       break;
  504.  
  505.     case C_INT:
  506.       (void) obstack_1grow (&tmp_mem, byte);
  507.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_int), sizeof (long));
  508.       break;
  509.  
  510.     case C_STR:
  511.       (void) obstack_1grow (&tmp_mem, byte);
  512.       node->add_byte = obstack_object_size (&tmp_mem);
  513.       (void) obstack_1grow (&tmp_mem, 0);
  514.       push_stack (str_stack, node);
  515.       break;
  516.  
  517.     case C_VAR:
  518.       add_ref_to (obstack_object_size (&tmp_mem));
  519.       add_var_ref (node->n_x.v_var);
  520.       (void) obstack_1grow (&tmp_mem, byte);
  521.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_var), sizeof (struct var *));
  522.       break;
  523.  
  524.     case C_CELL:
  525.       add_ref_to (obstack_object_size (&tmp_mem));
  526.       add_ref (node->n_x.v_rng.lr, node->n_x.v_rng.lc);
  527.       (void) obstack_1grow (&tmp_mem, byte);
  528. #if BITS_PER_CELLREF==16
  529.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lr >> 8);
  530.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lr);
  531.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lc >> 8);
  532.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lc);
  533. #else
  534. #if BITS_PER_CELLREF==8
  535.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lr);
  536.       (void) obstack_1grow (&tmp_mem, node->n_x.v_rng.lc);
  537. #else
  538.       Insert appropriate code here
  539. #endif
  540. #endif
  541.         break;
  542.  
  543.     case C_RANGE:
  544.       add_ref_to (obstack_object_size (&tmp_mem));
  545.       add_range_ref (&(node->n_x.v_rng));
  546.       (void) obstack_1grow (&tmp_mem, byte);
  547.       (void) obstack_grow (&tmp_mem, &(node->n_x.v_rng), sizeof (struct rng));
  548.       break;
  549.  
  550.     case C_FN0X:
  551.       add_ref_to (obstack_object_size (&tmp_mem));
  552.       /* FALLTHROUGH */
  553.     case C_FN0:
  554.     case C_CONST:
  555.     add_byte:
  556.       if (f->fn_comptype & C_T)
  557.     add_timer_ref (obstack_object_size (&tmp_mem));
  558.       (void) obstack_1grow (&tmp_mem, byte);
  559.       if (byte >= USR1 && byte < SKIP)
  560.     (void) obstack_1grow (&tmp_mem, (int) node->sub_value);
  561.       break;
  562.  
  563.     case C_FN1:
  564.     case C_UNA:
  565.       if (node->n_x.v_subs[0])
  566.     {
  567.       push_stack (fn_stack, node);
  568.       new_node = node->n_x.v_subs[0];
  569.       node->n_x.v_subs[0] = 0;
  570.       node = new_node;
  571.       goto loop;
  572.     }
  573.       goto add_byte;
  574.  
  575.     case C_FN2:
  576.     case C_INF:
  577.       if (node->n_x.v_subs[0])
  578.     {
  579.       push_stack (fn_stack, node);
  580.       new_node = node->n_x.v_subs[0];
  581.       node->n_x.v_subs[0] = 0;
  582.       node = new_node;
  583.       goto loop;
  584.     }
  585.       if (node->n_x.v_subs[1])
  586.     {
  587.       push_stack (fn_stack, node);
  588.       new_node = node->n_x.v_subs[1];
  589.       node->n_x.v_subs[1] = 0;
  590.       node = new_node;
  591.       goto loop;
  592.     }
  593.       goto add_byte;
  594.  
  595.     case C_FN3:
  596.       if (node->n_x.v_subs[0])
  597.     {
  598.       if (node->n_x.v_subs[0]->n_x.v_subs[0])
  599.         {
  600.           push_stack (fn_stack, node);
  601.           new_node = node->n_x.v_subs[0]->n_x.v_subs[0];
  602.           node->n_x.v_subs[0]->n_x.v_subs[0] = 0;
  603.           node = new_node;
  604.           goto loop;
  605.         }
  606.       push_stack (fn_stack, node);
  607.       new_node = node->n_x.v_subs[0]->n_x.v_subs[1];
  608.       node->n_x.v_subs[0] = 0;
  609.       node = new_node;
  610.       goto loop;
  611.     }
  612.       if (node->n_x.v_subs[1])
  613.     {
  614.       push_stack (fn_stack, node);
  615.       new_node = node->n_x.v_subs[1];
  616.       node->n_x.v_subs[1] = 0;
  617.       node = new_node;
  618.       goto loop;
  619.     }
  620.       goto add_byte;
  621.  
  622.     case C_FN4:
  623.       if (node->n_x.v_subs[0])
  624.     {
  625.       if (node->n_x.v_subs[0]->n_x.v_subs[0])
  626.         {
  627.           push_stack (fn_stack, node);
  628.           new_node = node->n_x.v_subs[0]->n_x.v_subs[0];
  629.           node->n_x.v_subs[0]->n_x.v_subs[0] = 0;
  630.           node = new_node;
  631.           goto loop;
  632.         }
  633.       push_stack (fn_stack, node);
  634.       new_node = node->n_x.v_subs[0]->n_x.v_subs[1];
  635.       node->n_x.v_subs[0] = 0;
  636.       node = new_node;
  637.       goto loop;
  638.     }
  639.       if (node->n_x.v_subs[1])
  640.     {
  641.       if (node->n_x.v_subs[1]->n_x.v_subs[0])
  642.         {
  643.           push_stack (fn_stack, node);
  644.           new_node = node->n_x.v_subs[1]->n_x.v_subs[0];
  645.           node->n_x.v_subs[1]->n_x.v_subs[0] = 0;
  646.           node = new_node;
  647.           goto loop;
  648.         }
  649.       push_stack (fn_stack, node);
  650.       new_node = node->n_x.v_subs[1]->n_x.v_subs[1];
  651.       node->n_x.v_subs[1] = 0;
  652.       node = new_node;
  653.       goto loop;
  654.     }
  655.       goto add_byte;
  656.  
  657.     case C_FNN:
  658.       if (node->n_x.v_subs[1])
  659.     {
  660.       if (node->add_byte == 0)
  661.         for (new_node = node; new_node->n_x.v_subs[1]; new_node = new_node->n_x.v_subs[1])
  662.           node->add_byte++;
  663.       for (new_node = node; new_node->n_x.v_subs[1]->n_x.v_subs[1]; new_node = new_node->n_x.v_subs[1])
  664.         ;
  665.       push_stack (fn_stack, node);
  666.       node = new_node->n_x.v_subs[1]->n_x.v_subs[0];
  667.       new_node->n_x.v_subs[1] = 0;
  668.       goto loop;
  669.     }
  670.       (void) obstack_1grow (&tmp_mem, byte);
  671.       if (byte >= USR1 && byte < SKIP)
  672.     (void) obstack_1grow (&tmp_mem, (int) node->sub_value);
  673.       (void) obstack_1grow (&tmp_mem, node->add_byte);
  674.       break;
  675.  
  676.     default:
  677.       panic ("Bad comptype %d", f->fn_comptype);
  678.     }
  679.   node = (struct node *) pop_stack (fn_stack);
  680.   if (node)
  681.     goto loop;
  682.  
  683.   (void) obstack_1grow (&tmp_mem, 0);
  684.  
  685.   while (node = pop_stack (str_stack))
  686.     {
  687.       add_backpatch (node->add_byte, obstack_object_size (&tmp_mem));
  688.       (void) obstack_grow (&tmp_mem, node->n_x.v_string, strlen (node->n_x.v_string) + 1);
  689.     }
  690.  
  691.   buf_siz = obstack_object_size (&tmp_mem);
  692.   ret = (unsigned char *) ck_malloc (buf_siz);
  693.   bcopy (obstack_finish (&tmp_mem), ret, buf_siz);
  694.  
  695.   need_relax = 0;
  696.   for (n = 0; n < patches_used; n++)
  697.     {
  698.       long offset;
  699.  
  700.       offset = (patches[n].to - patches[n].from) - 1;
  701.       if (offset < 0 || offset > 255)
  702.     need_relax++;
  703.       else
  704.     ret[patches[n].from] = offset;
  705.     }
  706.   if (need_relax)
  707.     {
  708.       int n_lo;
  709.       long offset;
  710.       int start;
  711.  
  712.       /* ... Sort the patches list ... */
  713.       sort (patches_used, cmp_patch, swp_patch, rot_patch);
  714.  
  715.       while (need_relax)
  716.     {
  717.       ret = ck_realloc (ret, buf_siz + need_relax);
  718.       for (n_lo = 0; n_lo < patches_used; n_lo++)
  719.         {
  720.           offset = (patches[n_lo].to - patches[n_lo].from) - 1;
  721.           if (offset < 0 || offset > 255 - need_relax)
  722.         break;
  723.         }
  724.  
  725.       /* n_lo points to the first jump that may need to be relaxed */
  726.       for (n = n_lo; n < patches_used; n++)
  727.         {
  728.           offset = (patches[n].to - patches[n].from) - 1;
  729.           if (offset < 0 || offset > 255)
  730.         {
  731.           int nn;
  732.  
  733.           start = patches[n].from;
  734.  
  735.           ret[start - 1]++;    /* Translate insn to LONG */
  736.           ret[start] = offset;
  737.           bcopy (&ret[start + 1], &ret[start + 2], buf_siz - start);
  738.           ret[start + 1] = offset >> 8;
  739.           need_relax--;
  740.           buf_siz++;
  741.           for (nn = 0; nn < patches_used; nn++)
  742.             {
  743.               if (patches[nn].from > start)
  744.             patches[nn].from++;
  745.               if (patches[nn].to > start)
  746.             patches[nn].to++;
  747.               if (patches[nn].from < start && patches[nn].to > start && ret[patches[nn].from]++ == 255)
  748.             {
  749.               if (ret[patches[nn].from - 1] & 01)
  750.                 ret[patches[nn].from + 1]++;
  751.               else
  752.                 need_relax++;
  753.             }
  754.             }
  755.         }
  756.         }
  757.     }
  758.     }
  759.  
  760.   (void) obstack_free (&tmp_mem, tmp_mem_start);
  761.  
  762.   patches_used = 0;
  763.  
  764.   return ret;
  765. }
  766.  
  767. /* Back when strings stored a char*, they needed to be freed when a
  768.    byte-compiled expression was freed.  Now that they're appended to the end,
  769.    they don't need to be specially freed anymore.
  770.  */
  771. void
  772. byte_free (form)
  773.      unsigned char *form;
  774. {
  775.   /* no longer needed
  776.     unsigned char *f;
  777.  
  778.     for(f=form;*f;f++) {
  779.         switch(*f) {
  780.         case IF:
  781.         case F_IF:
  782.         case SKIP:
  783.         case AND:
  784.         case OR:
  785.         case CONST_STR:
  786.             f++;
  787.             break;
  788.         case CONST_INT:
  789.             f+=sizeof(long);
  790.             break;
  791.         case CONST_FLT:
  792.             f+=sizeof(double);
  793.             break;
  794.         case VAR:
  795.             f+=sizeof(struct var *);
  796.             break;
  797.         case R_CELL:
  798.         case R_CELL|ROWREL:
  799.         case R_CELL|COLREL:
  800.         case R_CELL|ROWREL|COLREL:
  801.             f+=EXP_ADD;
  802.             break;
  803.         case RANGE:
  804.         case RANGE|LRREL:
  805.         case RANGE|LRREL|LCREL:
  806.         case RANGE|LRREL|LCREL|HCREL:
  807.         case RANGE|LRREL|HCREL:
  808.         case RANGE|LRREL|HRREL:
  809.         case RANGE|LRREL|HRREL|LCREL:
  810.         case RANGE|LRREL|HRREL|LCREL|HCREL:
  811.         case RANGE|LRREL|HRREL|HCREL:
  812.         case RANGE|HRREL:
  813.         case RANGE|HRREL|LCREL:
  814.         case RANGE|HRREL|LCREL|HCREL:
  815.         case RANGE|HRREL|HCREL:
  816.         case RANGE|LCREL:
  817.         case RANGE|LCREL|HCREL:
  818.         case RANGE|HCREL:
  819.             f+=EXP_ADD_RNG;
  820.             break;
  821.         case F_PRINTF:
  822.         case F_CONCAT:
  823.         case F_ONEOF:
  824.         case F_STRSTR:
  825.         case F_EDIT:
  826.         case AREA_SUM:
  827.         case AREA_PROD:
  828.         case AREA_AVG:
  829.         case AREA_STD:
  830.         case AREA_MAX:
  831.         case AREA_MIN:
  832.         case AREA_CNT:
  833.         case AREA_VAR:
  834.             f++;
  835.             break;
  836.         default:
  837.             break;
  838.         }
  839.     } */
  840.   free (form);
  841. }
  842.  
  843. /* This tries to tell if a byte-compiled expression is a constant.  If it
  844.    is a constant, we can free it, and never try to recompute its value.
  845.    This returns non-zero if the expression is constant.*/
  846. int
  847. is_constant (bytes)
  848.      unsigned char *bytes;
  849. {
  850.   /* It's constant, but it's already been dealt with.
  851.        Pretend it isn't. */
  852.   if (!bytes)
  853.     return 0;
  854.  
  855.   switch (bytes[0])
  856.     {
  857.     case CONST_ERR:
  858.       return (bytes[3] == 0 && !strcmp ((char *) bytes + 4, ename[bytes[2]]));
  859.     case CONST_INT:
  860.       return bytes[sizeof (long) + 1] == ENDCOMP;
  861.     case CONST_FLT:
  862.       return bytes[sizeof (double) + 1] == ENDCOMP;
  863.     case CONST_STR:
  864.       return bytes[2] == ENDCOMP;
  865.     case F_TRUE:
  866.     case F_FALSE:
  867.     case CONST_INF:
  868.     case CONST_NINF:
  869.     case CONST_NAN:
  870.       return bytes[1] == ENDCOMP;
  871.     default:
  872.       return 0;
  873.     }
  874. }
  875.